package org.threads.connectionpool;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.threads.connectionpool.myconnection.CreatingPoolException;
import org.utils.Utils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ProcessingThread implements Runnable {

    private static final Logger LOGGER = LoggerFactory.getLogger(ProcessingThread.class);

    /**
     * ConnectionTracking pool for obtaining an existing connections.
     */
    private final ConnectionPool connectionPool;

    private static final long MIN_PROCESSING_TIME = 100;
    private static final long MAX_PROCESSING_TIME = 1200;

    public ProcessingThread(final ConnectionPool connectionPool)
            throws IllegalArgumentException {

        if (connectionPool == null) {
            throw new IllegalArgumentException("ConnectionTracking pool is undefined!");
        }
        this.connectionPool = connectionPool;
    }

    /**
     * Entry point for custom thread.
     */
    @Override
    public void run() {

        while (true) {

            Connection con = null;
            while (true) {
                con = connectionPool.checkout();
                if (con != null) {
                    break;
                }
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    LOGGER.error("", e);
                }
            }

            try {

                Thread.sleep(Utils.getRandom(MIN_PROCESSING_TIME, MAX_PROCESSING_TIME));
                con.prepareStatement("CREATE TABLE testTable(id INT, name VARCHAR(10))");
                Thread.sleep(Utils.getRandom(MIN_PROCESSING_TIME, MAX_PROCESSING_TIME));
                con.prepareStatement("DROP TABLE testTable");

            } catch (InterruptedException ex) {
                LOGGER.error("", ex);
            } catch (SQLException ex) {
                LOGGER.error("", ex);
            } finally {
                connectionPool.checkin(con);
            }
        }
    }


    public static void main(String[] args) {

        ConnectionPool pool = null;

        try {
            pool = new ConnectionPool("org.h2.Driver", "jdbc:h2:~/test", "sa", "");
        } catch (CreatingPoolException e) {
            LOGGER.error("", e);
            return;
        }

        ExecutorService executor = Executors.newFixedThreadPool(50);
        Runnable procesingThread = new ProcessingThread(pool);

        try {
            for (int i = 0; i < 50; i++) {
                executor.submit(procesingThread);
            }

        } finally {
            executor.shutdown();
        }

    }

}
